<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Interactive BOM for KiCAD</title>
  <style type="text/css">
:root {
  --pcb-edge-color: black;
  --pad-color: #878787;
  --pad-color-highlight: #D04040;
  --pin1-outline-color: #ffb629;
  --pin1-outline-color-highlight: #b4ff03;
  --silkscreen-edge-color: #aa4;
  --silkscreen-polygon-color: #4aa;
  --silkscreen-text-color: #4aa;
  --fabrication-edge-color: #907651;
  --fabrication-polygon-color: #907651;
  --fabrication-text-color: #a27c24;
  --track-color: #def5f1;
  --track-color-highlight: #D04040;
  --zone-color: #def5f1;
  --zone-color-highlight: #d0404080;
}

html, body {
  margin: 0px;
  height: 100%;
  font-family: Verdana, sans-serif;
}

.dark.topmostdiv {
  --pcb-edge-color: #eee;
  --pad-color: #808080;
  --pin1-outline-color: #ffa800;
  --pin1-outline-color-highlight: #ccff00;
  --track-color: #42524f;
  --zone-color: #42524f;
  background-color: #252c30;
  color: #eee;
}

button {
  background-color: #eee;
  border: 1px solid #888;
  color: black;
  height: 44px;
  width: 44px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 14px;
  font-weight: bolder;
}

.dark button {
  /* This will be inverted */
  background-color: #c3b7b5;
}

button.depressed {
  background-color: #0a0;
  color: white;
}

.dark button.depressed {
  /* This will be inverted */
  background-color: #b3b;
}

button:focus {
  outline: 0;
}

button#tb-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.32 290.12h5.82M1.32 291.45h5.82' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 292.5v4.23M.26 292.63H8.2' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='1.35' y='295.73'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#lr-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.06 290.12H3.7m-2.64 1.33H3.7m-2.64 1.32H3.7m-2.64 1.3H3.7m-2.64 1.33H3.7' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 288.8v7.94m0-4.11h3.96' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='5.11' y='291.96'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#bom-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)' fill='none' stroke='%23000' stroke-width='.4'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' stroke-linejoin='round'/%3E%3Cpath d='M1.59 290.12h5.29M1.59 291.45h5.33M1.59 292.75h5.33M1.59 294.09h5.33M1.59 295.41h5.33'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-grouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m4 0h5m4 0h3M6.1 22h3m3.9 0h5m4 0h4m-16-8h4m4 0h4'/%3E%3Cpath stroke-linecap='null' d='M5 17.5h22M5 26.6h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-ungrouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m-4 8h3m-3 8h4'/%3E%3Cpath stroke-linecap='null' d='M5 13.5h22m-22 8h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-netlist-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg fill='none' stroke='%23000' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-width='2' d='M6 26l6-6v-8m13.8-6.3l-6 6v8'/%3E%3Ccircle cx='11.8' cy='9.5' r='2.8' stroke-width='2'/%3E%3Ccircle cx='19.8' cy='22.8' r='2.8' stroke-width='2'/%3E%3C/g%3E%3C/svg%3E");
}

button#copy {
  background-image: url("data:image/svg+xml,%3Csvg height='48' viewBox='0 0 48 48' width='48' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h48v48h-48z' fill='none'/%3E%3Cpath d='M32 2h-24c-2.21 0-4 1.79-4 4v28h4v-28h24v-4zm6 8h-22c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h22c2.21 0 4-1.79 4-4v-28c0-2.21-1.79-4-4-4zm0 32h-22v-28h22v28z'/%3E%3C/svg%3E");
  background-position: 6px 6px;
  background-repeat: no-repeat;
  background-size: 26px 26px;
  border-radius: 6px;
  height: 40px;
  width: 40px;
  margin: 10px 5px;
}

button#copy:active {
    box-shadow: inset 0px 0px 5px #6c6c6c;
}

textarea.clipboard-temp {
  position: fixed;
  top: 0;
  left: 0;
  width: 2em;
  height: 2em;
  padding: 0;
  border: None;
  outline: None;
  box-shadow: None;
  background: transparent;
}

.left-most-button {
  border-right: 0;
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}

.middle-button {
  border-right: 0;
}

.right-most-button {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}

.button-container {
  font-size: 0;
  margin: 10px 10px 10px 0px;
}

.dark .button-container {
  filter: invert(1);
}

.button-container button {
  background-size: 32px 32px;
  background-position: 5px 5px;
  background-repeat: no-repeat;
}

@media print {
  .hideonprint {
    display: none;
  }
}

canvas {
  cursor: crosshair;
}

canvas:active {
  cursor: grabbing;
}

.fileinfo {
  width: 100%;
  max-width: 1000px;
  border: none;
  padding: 5px;
}

.fileinfo .title {
  font-size: 20pt;
  font-weight: bold;
}

.fileinfo td {
  overflow: hidden;
  white-space: nowrap;
  max-width: 1px;
  width: 50%;
  text-overflow: ellipsis;
}

.bom {
  border-collapse: collapse;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 10pt;
  table-layout: fixed;
  width: 100%;
  margin-top: 1px;
}

.bom th, .bom td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

.dark .bom th, .dark .bom td {
  border: 1px solid #777;
}

.bom th {
  background-color: #CCCCCC;
  background-clip: padding-box;
}

.dark .bom th {
  background-color: #3b4749;
}

.bom tr.highlighted:nth-child(n) {
  background-color: #cfc;
}

.dark .bom tr.highlighted:nth-child(n) {
  background-color: #226022;
}

.bom tr:nth-child(even) {
  background-color: #f2f2f2;
}

.dark .bom tr:nth-child(even) {
  background-color: #313b40;
}

.bom tr.checked {
  color: #aaa;
}

.dark .bom tr.checked {
  color: #666;
}

.bom tr {
  transition: background-color 0.2s;
}

.bom .numCol {
  width: 25px;
}

.bom .Description {
  width: 10%;
}

.bom .Part {
  width: 10%;
}

.bom .Value {
  width: 15%;
}

.bom .Quantity {
  width: 65px;
}

.bom th .sortmark {
  position: absolute;
  right: 1px;
  top: 1px;
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent #221 transparent;
  transform-origin: 50% 85%;
  transition: opacity 0.2s, transform 0.4s;
}

.dark .bom th .sortmark {
  filter: invert(1);
}

.bom th .sortmark.none {
  opacity: 0;
}

.bom th .sortmark.desc {
  transform: rotate(180deg);
}

.bom th:hover .sortmark.none {
  opacity: 0.5;
}

.bom .bom-checkbox {
  width: 30px;
  position: relative;
  user-select: none;
  -moz-user-select: none;
}

.bom .bom-checkbox:before {
  content: "";
  position: absolute;
  border-width: 15px;
  border-style: solid;
  border-color: #51829f transparent transparent transparent;
  visibility: hidden;
  top: -15px;
}

.bom .bom-checkbox:after {
  content: "Double click to set/unset all";
  position: absolute;
  color: white;
  top: -35px;
  left: -26px;
  background: #51829f;
  padding: 5px 15px;
  border-radius: 8px;
  white-space: nowrap;
  visibility: hidden;
}

.bom .bom-checkbox:hover:before, .bom .bom-checkbox:hover:after {
  visibility: visible;
  transition: visibility 0.2s linear 1s;
}

.split {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  overflow-y: auto;
  overflow-x: hidden;
  background-color: inherit;
}

.split.split-horizontal, .gutter.gutter-horizontal {
  height: 100%;
  float: left;
}

.gutter {
  background-color: #ddd;
  background-repeat: no-repeat;
  background-position: 50%;
  transition: background-color 0.3s;
}

.dark .gutter {
  background-color: #777;
}

.gutter.gutter-horizontal {
  background-image: url('');
  cursor: ew-resize;
  width: 5px;
}

.gutter.gutter-vertical {
  background-image: url('');
  cursor: ns-resize;
  height: 5px;
}

.searchbox {
  float: left;
  height: 40px;
  margin: 10px 5px;
  padding: 12px 32px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 18px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 6px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  background-image: url('');
  background-position: 10px 10px;
  background-repeat: no-repeat;
}

.dark .searchbox {
  background-color: #111;
  color: #eee;
}

.searchbox::placeholder {
  color: #ccc;
}

.dark .searchbox::placeholder {
  color: #666;
}

.filter {
  width: calc(60% - 64px);
}

.reflookup {
  width: calc(40% - 10px);
}

input[type=text]:focus {
  background-color: white;
  border: 1px solid #333;
}

.dark input[type=text]:focus {
  background-color: #333;
  border: 1px solid #ccc;
}

mark.highlight {
  background-color: #5050ff;
  color: #fff;
  padding: 2px;
  border-radius: 6px;
}

.dark mark.highlight {
  background-color: #76a6da;
  color: #111;
}

.menubtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36' viewBox='0 0 20 20'%3E%3Cpath fill='none' d='M0 0h20v20H0V0z'/%3E%3Cpath d='M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z'/%3E%3C/svg%3E%0A");
  background-position: center;
  background-repeat: no-repeat;
}

.statsbtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg width='36' height='36' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 6h28v24H4V6zm0 8h28v8H4m9-16v24h10V5.8' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.iobtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='M3 33v-7l6.8-7h16.5l6.7 7v7H3zM3.2 26H33M21 9l5-5.9 5 6h-2.5V15h-5V9H21zm-4.9 0l-5 6-5-6h2.5V3h5v6h2.5z'/%3E%3Cpath fill='none' stroke='%23000' d='M6.1 29.5H10'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.dark .statsbtn, .dark .savebtn, .dark .menubtn, .dark .iobtn {
  filter: invert(1);
}

.flexbox {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.savebtn {
  background-color: #d6d6d6;
  width: auto;
  height: 30px;
  flex-grow: 1;
  margin: 5px;
  border-radius: 4px;
}

.savebtn:active {
  background-color: #0a0;
  color: white;
}

.dark .savebtn:active {
  /* This will be inverted */
  background-color: #b3b;
}

.stats {
  border-collapse: collapse;
  font-size: 12pt;
  table-layout: fixed;
  width: 100%;
  min-width: 450px;
}

.dark .stats td {
  border: 1px solid #bbb;
}

.stats td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

#checkbox-stats div {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

#checkbox-stats .bar {
  background-color: rgba(28, 251, 0, 0.6);
}

.menu {
  position: relative;
  display: inline-block;
  margin: 10px 10px 10px 0px;
}

.menu-content {
  display: none;
  position: absolute;
  background-color: white;
  right: 0;
  min-width: 300px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 100;
  padding: 8px;
}

.dark .menu-content {
  background-color: #111;
}

.menu:hover .menu-content {
  display: block;
}

.menu:hover .menubtn, .menu:hover .iobtn, .menu:hover .statsbtn {
  background-color: #eee;
}

.menu-label {
  display: inline-block;
  padding: 8px;
  border: 1px solid #ccc;
  border-top: 0;
  width: calc(100% - 18px);
}

.menu-label-top {
  border-top: 1px solid #ccc;
}

.menu-textbox {
  float: left;
  height: 24px;
  margin: 10px 5px;
  padding: 5px 5px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 14px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 4px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  width: calc(100% - 10px);
}

.menu-textbox.invalid, .dark .menu-textbox.invalid {
  color: red;
}

.dark .menu-textbox {
  background-color: #222;
  color: #eee;
}

.radio-container {
  margin: 4px;
}

.topmostdiv {
  width: 100%;
  height: 100%;
  background-color: white;
  transition: background-color 0.3s;
}

#top {
  height: 78px;
  border-bottom: 2px solid black;
}

.dark #top {
  border-bottom: 2px solid #ccc;
}

#dbg {
  display: block;
}

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: #aaa;
}

::-webkit-scrollbar-thumb {
  background: #666;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #555;
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  margin: 3px 0;
  padding: 0;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
  border-radius: 3px;
}

.slider:hover {
  opacity: 1;
}

.slider:focus {
  outline: none;
}

.slider::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  width: 100%;
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
  border: none;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin-top: -4px;
}

.dark .slider::-webkit-slider-thumb {
  background: #3d3;
}

.slider::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
}

.slider::-moz-range-track {
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
}

.dark .slider::-moz-range-thumb {
  background: #3d3;
}

.slider::-ms-track {
  width: 100%;
  height: 8px;
  border-width: 3px 0;
  background: transparent;
  border-color: transparent;
  color: transparent;
  transition: opacity .2s;
}

.slider::-ms-fill-lower {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-fill-upper {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin: 0;
}

.shameless-plug {
  font-size: 0.8em;
  text-align: center;
  display: block;
}

a {
  color: #0278a4;
}

.dark a {
  color: #00b9fd;
}

#frontcanvas, #backcanvas {
    touch-action: none;
}

  </style>
  <script type="text/javascript" >
///////////////////////////////////////////////
/*
  Split.js - v1.3.5
  MIT License
  https://github.com/nathancahill/Split.js
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f<s.minSize&&(s.minSize=f),t>0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}});

///////////////////////////////////////////////

///////////////////////////////////////////////
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
// This work is free. You can redistribute it and/or modify it
// under the terms of the WTFPL, Version 2
// For more information see LICENSE.txt or http://www.wtfpl.net/
//
// For more information, the home page:
// http://pieroxy.net/blog/pages/lz-string/testing.html
//
// LZ-based compression algorithm, version 1.4.4
var LZString=function(){var o=String.fromCharCode,i={};var n={decompressFromBase64:function(o){return null==o?"":""==o?null:n._decompress(o.length,32,function(n){return function(o,n){if(!i[o]){i[o]={};for(var t=0;t<o.length;t++)i[o][o.charAt(t)]=t}return i[o][n]}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o.charAt(n))})},_decompress:function(i,n,t){var r,e,a,s,p,u,l,f=[],c=4,d=4,h=3,v="",g=[],m={val:t(0),position:n,index:1};for(r=0;r<3;r+=1)f[r]=r;for(a=0,p=Math.pow(2,2),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 2:return""}for(f[3]=l,e=l,g.push(l);;){if(m.index>i)return"";for(a=0,p=Math.pow(2,h),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(l=a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 2:return g.join("")}if(0==c&&(c=Math.pow(2,h),h++),f[l])v=f[l];else{if(l!==d)return null;v=e+e.charAt(0)}g.push(v),f[d++]=e+v.charAt(0),e=v,0==--c&&(c=Math.pow(2,h),h++)}}};return n}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString});
///////////////////////////////////////////////

///////////////////////////////////////////////
/*!
 * PEP v0.4.3 | https://github.com/jquery/PEP
 * Copyright jQuery Foundation and other contributors | http://jquery.org/license
 */
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PointerEventsPolyfill=b()}(this,function(){"use strict";function a(a,b){b=b||Object.create(null);var c=document.createEvent("Event");c.initEvent(a,b.bubbles||!1,b.cancelable||!1);
for(var d,e=2;e<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0;
var f=0;return f=b.pressure&&c.buttons?b.pressure:c.buttons?.5:0,c.x=c.clientX,c.y=c.clientY,c.pointerId=b.pointerId||0,c.width=b.width||0,c.height=b.height||0,c.pressure=f,c.tiltX=b.tiltX||0,c.tiltY=b.tiltY||0,c.twist=b.twist||0,c.tangentialPressure=b.tangentialPressure||0,c.pointerType=b.pointerType||"",c.hwTimestamp=b.hwTimestamp||0,c.isPrimary=b.isPrimary||!1,c}function b(){this.array=[],this.size=0}function c(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),A&&(this.observer=new A(this.mutationWatcher.bind(this)))}function d(a){return"body /shadow-deep/ "+e(a)}function e(a){return'[touch-action="'+a+'"]'}function f(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; }"}function g(){if(F){D.forEach(function(a){String(a)===a?(E+=e(a)+f(a)+"\n",G&&(E+=d(a)+f(a)+"\n")):(E+=a.selectors.map(e)+f(a.rule)+"\n",G&&(E+=a.selectors.map(d)+f(a.rule)+"\n"))});var a=document.createElement("style");a.textContent=E,document.head.appendChild(a)}}function h(){if(!window.PointerEvent){if(window.PointerEvent=a,window.navigator.msPointerEnabled){var b=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:b,enumerable:!0}),u.registerSource("ms",_)}else Object.defineProperty(window.navigator,"maxTouchPoints",{value:0,enumerable:!0}),u.registerSource("mouse",N),void 0!==window.ontouchstart&&u.registerSource("touch",V);u.register(document)}}function i(a){if(!u.pointermap.has(a)){var b=new Error("InvalidPointerId");throw b.name="InvalidPointerId",b}}function j(a){for(var b=a.parentNode;b&&b!==a.ownerDocument;)b=b.parentNode;if(!b){var c=new Error("InvalidStateError");throw c.name="InvalidStateError",c}}function k(a){var b=u.pointermap.get(a);return 0!==b.buttons}function l(){window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:W},releasePointerCapture:{value:X},hasPointerCapture:{value:Y}})}
var m=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","pageX","pageY"],n=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0],o=window.Map&&window.Map.prototype.forEach,p=o?Map:b;b.prototype={set:function(a,b){return void 0===b?this["delete"](a):(this.has(a)||this.size++,void(this.array[a]=b))},has:function(a){return void 0!==this.array[a]},"delete":function(a){this.has(a)&&(delete this.array[a],this.size--)},get:function(a){return this.array[a]},clear:function(){this.array.length=0,this.size=0},forEach:function(a,b){return this.array.forEach(function(c,d){a.call(b,c,d,this)},this)}};var q=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which","pageX","pageY","timeStamp"],r=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],s={pointerover:1,pointerout:1,pointerenter:1,pointerleave:1},t="undefined"!=typeof SVGElementInstance,u={pointermap:new p,eventMap:Object.create(null),captureInfo:Object.create(null),eventSources:Object.create(null),eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
b.unregister.call(b,a)},contains:function(a,b){try{return a.contains(b)}catch(c){return!1}},down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.propagate(a,this.leave,!1)},enterOver:function(a){this.over(a),this.propagate(a,this.enter,!0)},eventHandler:function(a){if(!a._handledByPE){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),a._handledByPE=!0}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(b,c){this.captureInfo[c.pointerId]&&(c.relatedTarget=null);var d=new a(b,c);return c.preventDefault&&(d.preventDefault=c.preventDefault),d._target=d._target||c.target,d},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var b,c=Object.create(null),d=0;d<q.length;d++)b=q[d],c[b]=a[b]||r[d],!t||"target"!==b&&"relatedTarget"!==b||c[b]instanceof SVGElementInstance&&(c[b]=c[b].correspondingUseElement);return a.preventDefault&&(c.preventDefault=function(){a.preventDefault()}),c},getTarget:function(a){var b=this.captureInfo[a.pointerId];return b?a._target!==b&&a.type in s?void 0:b:a._target},propagate:function(a,b,c){for(var d=a.target,e=[];d!==document&&!d.contains(a.relatedTarget);) if(e.push(d),d=d.parentNode,!d)return;c&&e.reverse(),e.forEach(function(c){a.target=c,b.call(this,a)},this)},setCapture:function(b,c,d){this.captureInfo[b]&&this.releaseCapture(b,d),this.captureInfo[b]=c,this.implicitRelease=this.releaseCapture.bind(this,b,d),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease);var e=new a("gotpointercapture");e.pointerId=b,e._target=c,d||this.asyncDispatchEvent(e)},releaseCapture:function(b,c){var d=this.captureInfo[b];if(d){this.captureInfo[b]=void 0,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease);var e=new a("lostpointercapture");e.pointerId=b,e._target=d,c||this.asyncDispatchEvent(e)}},dispatchEvent:/*scope.external.dispatchEvent || */function(a){var b=this.getTarget(a);if(b)return b.dispatchEvent(a)},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};u.boundHandler=u.eventHandler.bind(u);var v={shadow:function(a){if(a)return a.shadowRoot||a.webkitShadowRoot},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);if(this.canTarget(b))return b},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d} e=this.olderShadow(e)} return f}},owner:function(a){
for(var b=a;b.parentNode;)b=b.parentNode;
return b.nodeType!==Node.DOCUMENT_NODE&&b.nodeType!==Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);
return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}},w=Array.prototype.forEach.call.bind(Array.prototype.forEach),x=Array.prototype.map.call.bind(Array.prototype.map),y=Array.prototype.slice.call.bind(Array.prototype.slice),z=Array.prototype.filter.call.bind(Array.prototype.filter),A=window.MutationObserver||window.WebKitMutationObserver,B="[touch-action]",C={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};c.prototype={watchSubtree:function(a){
//
this.observer&&v.canTarget(a)&&this.observer.observe(a,C)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){w(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(B):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(y(b))},
installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){
var b=x(a,this.findElements,this);
return b.push(z(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}};var D=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],E="",F=window.PointerEvent||window.MSPointerEvent,G=!window.ShadowDOMPolyfill&&document.head.createShadowRoot,H=u.pointermap,I=25,J=[1,4,2,8,16],K=!1;try{K=1===new MouseEvent("test",{buttons:1}).buttons}catch(L){}
var M,N={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},lastTouches:[],
isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,d=a.clientX,e=a.clientY,f=0,g=c.length;f<g&&(b=c[f]);f++){
var h=Math.abs(d-b.x),i=Math.abs(e-b.y);if(h<=I&&i<=I)return!0}},prepareEvent:function(a){var b=u.cloneEvent(a),c=b.preventDefault;return b.preventDefault=function(){a.preventDefault(),c()},b.pointerId=this.POINTER_ID,b.isPrimary=!0,b.pointerType=this.POINTER_TYPE,b},prepareButtonsForMove:function(a,b){var c=H.get(this.POINTER_ID);
0!==b.which&&c?a.buttons=c.buttons:a.buttons=0,b.buttons=a.buttons},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);K||(c.buttons=J[c.button],b&&(c.buttons|=b.buttons),a.buttons=c.buttons),H.set(this.POINTER_ID,a),b&&0!==b.buttons?u.move(c):u.down(c)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.move(b)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);if(!K){var d=J[c.button];
c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a),
c.buttons&=~J[c.button],0===c.buttons?u.up(c):u.move(c)}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.enterOver(b)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,u.leaveOut(b)}},cancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.deactivateMouse()},deactivateMouse:function(){H["delete"](this.POINTER_ID)}},O=u.captureInfo,P=v.findTarget.bind(v),Q=v.allShadows.bind(v),R=u.pointermap,S=2500,T=200,U="touch-action",V={events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){M.enableOnSubtree(a)},unregister:function(){},elementAdded:function(a){var b=a.getAttribute(U),c=this.touchActionToScrollType(b);c&&(a._scrollType=c,u.listen(a,this.events),
Q(a).forEach(function(a){a._scrollType=c,u.listen(a,this.events)},this))},elementRemoved:function(a){a._scrollType=void 0,u.unlisten(a,this.events),
Q(a).forEach(function(a){a._scrollType=void 0,u.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(U),d=this.touchActionToScrollType(c),e=this.touchActionToScrollType(b);
d&&e?(a._scrollType=d,Q(a).forEach(function(a){a._scrollType=d},this)):e?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){
(0===R.size||1===R.size&&R.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,T)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return"touchstart"!==a&&"touchmove"!==a||(b=1),b},touchToPointer:function(a){var b=this.currentTouchEvent,c=u.cloneEvent(a),d=c.pointerId=a.identifier+2;c.target=O[d]||P(c),c.bubbles=!0,c.cancelable=!0,c.detail=this.clickCount,c.button=0,c.buttons=this.typeToButtons(b.type),c.width=2*(a.radiusX||a.webkitRadiusX||0),c.height=2*(a.radiusY||a.webkitRadiusY||0),c.pressure=a.force||a.webkitForce||.5,c.isPrimary=this.isPrimaryTouch(a),c.pointerType=this.POINTER_TYPE,
c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey;
var e=this;return c.preventDefault=function(){e.scrolling=!1,e.firstXY=null,b.preventDefault()},c},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a;for(var d,e=0;e<c.length;e++)d=c[e],b.call(this,this.touchToPointer(d))},
shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c)
b=!1;else if("XY"===c)
b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);
b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;d<e&&(c=a[d]);d++)if(c.identifier===b)return!0},
vacuumTouches:function(a){var b=a.touches;
if(R.size>=b.length){var c=[];R.forEach(function(a,d){
if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(e)}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){R.set(a.pointerId,{target:a.target,out:a,outTarget:a.target}),u.enterOver(a),u.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,c=R.get(b.pointerId);
if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e,
d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):(
b.target=e,b.relatedTarget=null,this.cancelOut(b))),c.out=b,c.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(u.up(a),u.leaveOut(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){u.cancel(a),u.leaveOut(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){R["delete"](a.pointerId),this.removePrimaryPointer(a)},
dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0];
if(this.isPrimaryTouch(c)){
var d={x:c.clientX,y:c.clientY};b.push(d);var e=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,b,d);setTimeout(e,S)}}};M=new c(V.elementAdded,V.elementRemoved,V.elementChanged,V);var W,X,Y,Z=u.pointermap,$=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,_={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var b=a;return $&&(b=u.cloneEvent(a),b.pointerType=this.POINTER_TYPES[a.pointerType]),b},cleanup:function(a){Z["delete"](a)},MSPointerDown:function(a){Z.set(a.pointerId,a);var b=this.prepareEvent(a);u.down(b)},MSPointerMove:function(a){var b=this.prepareEvent(a);u.move(b)},MSPointerUp:function(a){var b=this.prepareEvent(a);u.up(b),this.cleanup(a.pointerId)},MSPointerOut:function(a){var b=this.prepareEvent(a);u.leaveOut(b)},MSPointerOver:function(a){var b=this.prepareEvent(a);u.enterOver(b)},MSPointerCancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var b=u.makeEvent("lostpointercapture",a);u.dispatchEvent(b)},MSGotPointerCapture:function(a){var b=u.makeEvent("gotpointercapture",a);u.dispatchEvent(b)}},aa=window.navigator;aa.msPointerEnabled?(W=function(a){i(a),j(this),k(a)&&(u.setCapture(a,this,!0),this.msSetPointerCapture(a))},X=function(a){i(a),u.releaseCapture(a,!0),this.msReleasePointerCapture(a)}):(W=function(a){i(a),j(this),k(a)&&u.setCapture(a,this)},X=function(a){i(a),u.releaseCapture(a)}),Y=function(a){return!!u.captureInfo[a]},g(),h(),l();var ba={dispatcher:u,Installer:c,PointerEvent:a,PointerMap:p,targetFinding:v};return ba});

///////////////////////////////////////////////

///////////////////////////////////////////////
var config = {"highlight_pin1": false, "checkboxes": "Sourced,Placed", "show_fabrication": false, "extra_fields": [], "show_silkscreen": true, "board_rotation": 0, "redraw_on_drag": true, "show_pads": true, "bom_view": "left-right", "dark_mode": true, "layer_view": "FB"}
///////////////////////////////////////////////

///////////////////////////////////////////////
var pcbdata = JSON.parse(LZString.decompressFromBase64("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q3SqTKQSyqvirCK7quIrLyjqvEqz848siqQqkaoarny3hOmqJq3ipgqzivqq8rsq7Ioir1qgoowrMSoas6r7K50sarZYPapZKoq6qoaKD0A6trLcS5Ys0qIYM6u5L/Ky6u2rPK4yscKTqzpCuqXKqquoKa8/Ss+oNiwBH+K5qhyoWqgE3yuBq/XJSvMrQS9vIOKZK46ohrl4ZyrmK/i3irILv8+GruKNq0apQK0at4oRrJq/6qhrAuTYrxr5qsqusr1i24vEQSazQtyroa0GtaKhK8KpsryakGt4qXC14pxr6aymvBrqavktirOamGoKqIqvmsRquqqmvTyeazErpqXvNKolrRalmoeLNq3dPSrJahmpSKZS34opqPqvEq+qVIH6vRqKa3atiqFa26s7KHqgrBFqLi3opNqia3GoNr7qo2ttrdarWt4qSKg9BVqBa5GqFqRmCWstqVqqitNqual2o5LJK9Yt9qCi0Oqdr+aiOs4qISj2pjqpS8coPRg6xOptqRKs4s9qmSkEt9qs6t2vTq9i4msxrCauAofL6qwWurzfKyupJLWqmgsBr0CnuAIrWasKt3SK6j0v7KsayBBwTW6v2tQqUavSoHy8wiAv6r3KrwvrriqhKvxqfKn4v7q/8r2svLp6turVq562tKXKp67urcqrYlisXqb8ouuHrpi/ep3rG6retgLx6wepMrj6tqt1qD6iet7oF69/KPqA6i+r7qr682vvqX6pGqHqA672uPyLqysqeqf86/LXr5S9WvQqwK1eq9rHah+uvrPq2+vdrRK+BodqIqmBtfqYyuBs/q06uOowbf6m+oDqS6t/JaqySvBqvrMGscrwaz6skrrqKGghsQaiG8hrAaVquup/rpamurHK6GlhuLBRgPcORB5gdgHYBwYHsD4aWARnywAZ3foBxwKQJACtAWwkACsBbAewEcA6RByNQi4ojCP4dPgRmxoRvw2uwwjK1A4EZsyAfRsMaN4Exp8h8AAxtfCIcIEEZsEwNMGsbiIs92yAHGwumcakwTtAARLGsxq8a4Zb8M9tTGzxvcAoSexs9s9GkJrDoowXRr+BvwwwGIjRwDqFiarqRJruo3GoJrahfANJuSbPbIiSiakmjJpAh9gVJoSavGwpsZt0wbJvKb0mxm2pgdGmppibPbO0iiaFYbNkZt2QVpvCxyADpragQmsL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"))
///////////////////////////////////////////////

///////////////////////////////////////////////
/* Utility functions */

var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' +
  pcbdata.metadata.revision + '__#';
var storage;

function initStorage(key) {
  try {
    window.localStorage.getItem("blank");
    storage = window.localStorage;
  } catch (e) {
    // localStorage not available
  }
  if (!storage) {
    try {
      window.sessionStorage.getItem("blank");
      storage = window.sessionStorage;
    } catch (e) {
      // sessionStorage also not available
    }
  }
}

function readStorage(key) {
  if (storage) {
    return storage.getItem(storagePrefix + key);
  } else {
    return null;
  }
}

function writeStorage(key, value) {
  if (storage) {
    storage.setItem(storagePrefix + key, value);
  }
}

function fancyDblClickHandler(el, onsingle, ondouble) {
  return function() {
    if (el.getAttribute("data-dblclick") == null) {
      el.setAttribute("data-dblclick", 1);
      setTimeout(function() {
        if (el.getAttribute("data-dblclick") == 1) {
          onsingle();
        }
        el.removeAttribute("data-dblclick");
      }, 200);
    } else {
      el.removeAttribute("data-dblclick");
      ondouble();
    }
  }
}

function smoothScrollToRow(rowid) {
  document.getElementById(rowid).scrollIntoView({
    behavior: "smooth",
    block: "center",
    inline: "nearest"
  });
}

function focusInputField(input) {
  input.scrollIntoView(false);
  input.focus();
  input.select();
}

function copyToClipboard() {
  var text = '';
  for (var node of bomhead.childNodes[0].childNodes) {
    if (node.firstChild) {
      text = text + node.firstChild.nodeValue;
    }
    if (node != bomhead.childNodes[0].lastChild) {
      text += '\t';
    }
  }
  text += '\n';
  for (var row of bombody.childNodes) {
    for (var cell of row.childNodes) {
      for (var node of cell.childNodes) {
        if (node.nodeName == "INPUT") {
          if (node.checked) {
            text = text + '✓';
          }
        } else if (node.nodeName == "MARK") {
          text = text + node.firstChild.nodeValue;
        } else {
          text = text + node.nodeValue;
        }
      }
      if (cell != row.lastChild) {
        text += '\t';
      }
    }
    text += '\n';
  }
  var textArea = document.createElement("textarea");
  textArea.classList.add('clipboard-temp');
  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    if (document.execCommand('copy')) {
      console.log('Bom copied to clipboard.');
    }
  } catch (err) {
    console.log('Can not copy to clipboard.');
  }

  document.body.removeChild(textArea);
}

function removeGutterNode(node) {
  for (var i = 0; i < node.childNodes.length; i++) {
    if (node.childNodes[i].classList &&
      node.childNodes[i].classList.contains("gutter")) {
      node.removeChild(node.childNodes[i]);
      break;
    }
  }
}

function cleanGutters() {
  removeGutterNode(document.getElementById("bot"));
  removeGutterNode(document.getElementById("canvasdiv"));
}

var units = {
  prefixes: {
    giga: ["G", "g", "giga", "Giga", "GIGA"],
    mega: ["M", "mega", "Mega", "MEGA"],
    kilo: ["K", "k", "kilo", "Kilo", "KILO"],
    milli: ["m", "milli", "Milli", "MILLI"],
    micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
    nano: ["N", "n", "nano", "Nano", "NANO"],
    pico: ["P", "p", "pico", "Pico", "PICO"],
  },
  unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
  unitsLong: [
    "OHM", "Ohm", "ohm", "ohms",
    "FARAD", "Farad", "farad",
    "HENRY", "Henry", "henry"
  ],
  getMultiplier: function(s) {
    if (this.prefixes.giga.includes(s)) return 1e9;
    if (this.prefixes.mega.includes(s)) return 1e6;
    if (this.prefixes.kilo.includes(s)) return 1e3;
    if (this.prefixes.milli.includes(s)) return 1e-3;
    if (this.prefixes.micro.includes(s)) return 1e-6;
    if (this.prefixes.nano.includes(s)) return 1e-9;
    if (this.prefixes.pico.includes(s)) return 1e-12;
    return 1;
  },
  valueRegex: null,
}

function initUtils() {
  var allPrefixes = units.prefixes.giga
                    .concat(units.prefixes.mega)
                    .concat(units.prefixes.kilo)
                    .concat(units.prefixes.milli)
                    .concat(units.prefixes.micro)
                    .concat(units.prefixes.nano)
                    .concat(units.prefixes.pico);
  var allUnits = units.unitsShort.concat(units.unitsLong);
  units.valueRegex = new RegExp("^([0-9\.]+)" +
                         "\\s*(" + allPrefixes.join("|") + ")?" +
                         "(" + allUnits.join("|") + ")?" +
                         "(\\b.*)?$", "");
  units.valueAltRegex = new RegExp("^([0-9]*)" +
                         "(" + units.unitsShort.join("|") + ")?" +
                         "([GgMmKkUuNnPp])?" +
                         "([0-9]*)" +
                         "(\\b.*)?$", "");
  for (var bom_type of ["both", "F", "B"]) {
    for (var row of pcbdata.bom[bom_type]) {
      row.push(parseValue(row[1], row[3][0][0]));
    }
  }
}

function parseValue(val, ref) {
  var inferUnit = (unit, ref) => {
    if (unit) {
      unit = unit.toLowerCase();
      if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
        unit = 'r';
      }
      unit = unit[0];
    } else {
      ref = /^([a-z]+)\d+$/i.exec(ref);
      if (ref) {
        ref = ref[1].toLowerCase();
        if (ref == "c") unit = 'f';
        else if (ref == "l") unit = 'h';
        else if (ref == "r" || ref == "rv") unit = 'r';
        else unit = null;
      }
    }
    return unit;
  };
  val = val.replace(/,/g, "");
  var match = units.valueRegex.exec(val);
  var unit;
  if (match) {
    val = parseFloat(match[1]);
    if (match[2]) {
      val = val * units.getMultiplier(match[2]);
    }
    unit = inferUnit(match[3], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[4],
    }
  }
  match = units.valueAltRegex.exec(val);
  if (match && (match[1] || match[4])) {
    val = parseFloat(match[1] + "." + match[4]);
    if (match[3]) {
      val = val * units.getMultiplier(match[3]);
    }
    unit = inferUnit(match[2], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[5],
    }
  }
  return null;
}

function valueCompare(a, b, stra, strb) {
  if (a === null && b === null) {
    // Failed to parse both values, compare them as strings.
    if (stra != strb) return stra > strb ? 1 : -1;
    else return 0;
  } else if (a === null) {
    return 1;
  } else if (b === null) {
    return -1;
  } else {
    if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
    else if (a.val != b.val) return a.val > b.val ? 1 : -1;
    else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
    else return 0;
  }
}

function validateSaveImgDimension(element) {
  var valid = false;
  var intValue = 0;
  if (/^[1-9]\d*$/.test(element.value)) {
    intValue = parseInt(element.value);
    if (intValue <= 16000) {
      valid = true;
    }
  }
  if (valid) {
    element.classList.remove("invalid");
  } else {
    element.classList.add("invalid");
  }
  return intValue;
}

function saveImage(layer) {
  var width = validateSaveImgDimension(document.getElementById("render-save-width"));
  var height = validateSaveImgDimension(document.getElementById("render-save-height"));
  var bgcolor = null;
  if (!document.getElementById("render-save-transparent").checked) {
    var style = getComputedStyle(topmostdiv);
    bgcolor = style.getPropertyValue("background-color");
  }
  if (!width || !height) return;

  // Prepare image
  var canvas = document.createElement("canvas");
  var layerdict = {
    transform: {
      x: 0,
      y: 0,
      s: 1,
      panx: 0,
      pany: 0,
      zoom: 1,
    },
    bg: canvas,
    fab: canvas,
    silk: canvas,
    highlight: canvas,
    layer: layer,
  }
  // Do the rendering
  recalcLayerScale(layerdict, width, height);
  prepareLayer(layerdict);
  clearCanvas(canvas, bgcolor);
  drawBackground(layerdict, false);
  drawHighlightsOnLayer(layerdict, false);

  // Save image
  var imgdata = canvas.toDataURL("image/png");

  var filename = pcbdata.metadata.title;
  if (pcbdata.metadata.revision) {
    filename += `.${pcbdata.metadata.revision}`;
  }
  filename += `.${layer}.png`;
  saveFile(filename, dataURLtoBlob(imgdata));
}

function saveSettings() {
  var data = {
    type: "InteractiveHtmlBom settings",
    version: 1,
    pcbmetadata: pcbdata.metadata,
    settings: settings,
  }
  var blob = new Blob([JSON.stringify(data, null, 4)], {type: "application/json"});
  saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
}

function loadSettings() {
  var input = document.createElement("input");
  input.type = "file";
  input.accept = ".settings.json";
  input.onchange = function(e) {
    var file = e.target.files[0];
    var reader = new FileReader();
    reader.onload = readerEvent => {
      var content = readerEvent.target.result;
      var newSettings;
      try {
        newSettings = JSON.parse(content);
      } catch(e) {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      if (newSettings.type != "InteractiveHtmlBom settings") {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
      if (metadataMatches) {
        for (var k in pcbdata.metadata) {
          if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
            metadataMatches = false;
          }
        }
      }
      if (!metadataMatches) {
        var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
        var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
        if (!confirm(
          `Settins file metadata does not match current metadata.\n\n` +
          `Page metadata:\n${currentMetadata}\n\n` +
          `Settings file metadata:\n${fileMetadata}\n\n` +
          `Press OK if you would like to import settings anyway.`)) {
          return;
        }
      }
      overwriteSettings(newSettings.settings);
    }
    reader.readAsText(file, 'UTF-8');
  }
  input.click();
}

function overwriteSettings(newSettings) {
  initDone = false;
  Object.assign(settings, newSettings);
  writeStorage("bomlayout", settings.bomlayout);
  writeStorage("bommode", settings.bommode);
  writeStorage("canvaslayout", settings.canvaslayout);
  writeStorage("bomCheckboxes", settings.checkboxes.join(","));
  document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
  for (var checkbox of settings.checkboxes) {
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
  }
  writeStorage("darkenWhenChecked", settings.darkenWhenChecked);
  padsVisible(settings.renderPads);
  document.getElementById("padsCheckbox").checked = settings.renderPads;
  fabricationVisible(settings.renderFabrication);
  document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
  silkscreenVisible(settings.renderSilkscreen);
  document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
  referencesVisible(settings.renderReferences);
  document.getElementById("referencesCheckbox").checked = settings.renderReferences;
  valuesVisible(settings.renderValues);
  document.getElementById("valuesCheckbox").checked = settings.renderValues;
  tracksVisible(settings.renderTracks);
  document.getElementById("tracksCheckbox").checked = settings.renderTracks;
  zonesVisible(settings.renderZones);
  document.getElementById("zonesCheckbox").checked = settings.renderZones;
  dnpOutline(settings.renderDnpOutline);
  document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
  setRedrawOnDrag(settings.redrawOnDrag);
  document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
  setDarkMode(settings.darkMode);
  document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
  setHighlightPin1(settings.highlightpin1);
  document.getElementById("highlightpin1Checkbox").checked = settings.highlightpin1;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  initDone = true;
  prepCheckboxes();
  changeBomLayout(settings.bomlayout);
}

function saveFile(filename, blob) {
  var link = document.createElement("a");
  var objurl = URL.createObjectURL(blob);
  link.download = filename;
  link.href = objurl;
  link.click();
}

function dataURLtoBlob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while(n--){
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], {type:mime});
}

var settings = {
  canvaslayout: "default",
  bomlayout: "default",
  bommode: "grouped",
  checkboxes: [],
  checkboxStoredRefs: {},
  darkMode: false,
  highlightpin1: false,
  redrawOnDrag: true,
  boardRotation: 0,
  renderPads: true,
  renderReferences: true,
  renderValues: true,
  renderSilkscreen: true,
  renderFabrication: true,
  renderDnpOutline: false,
  renderTracks: true,
  renderZones: true,
}

function initDefaults() {
  settings.bomlayout = readStorage("bomlayout");
  if (settings.bomlayout === null) {
    settings.bomlayout = config.bom_view;
  }
  if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) {
    settings.bomlayout = config.bom_view;
  }
  settings.bommode = readStorage("bommode");
  if (settings.bommode === null) {
    settings.bommode = "grouped";
  }
  if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) {
    settings.bommode = "grouped";
  }
  settings.canvaslayout = readStorage("canvaslayout");
  if (settings.canvaslayout === null) {
    settings.canvaslayout = config.layer_view;
  }
  var bomCheckboxes = readStorage("bomCheckboxes");
  if (bomCheckboxes === null) {
    bomCheckboxes = config.checkboxes;
  }
  settings.checkboxes = bomCheckboxes.split(",").filter((e) => e);
  document.getElementById("bomCheckboxes").value = bomCheckboxes;

  settings.darkenWhenChecked = readStorage("darkenWhenChecked") || "";
  populateDarkenWhenCheckedOptions();

  function initBooleanSetting(storageString, def, elementId, func) {
    var b = readStorage(storageString);
    if (b === null) {
      b = def;
    } else {
      b = (b == "true");
    }
    document.getElementById(elementId).checked = b;
    func(b);
  }

  initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
  initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
  initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
  initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
  initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible);
  if ("tracks" in pcbdata) {
    initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
    initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
  } else {
    document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
    tracksVisible(false);
    zonesVisible(false);
  }
  initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
  initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
  initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
  initBooleanSetting("highlightpin1", config.highlight_pin1, "highlightpin1Checkbox", setHighlightPin1);
  settings.boardRotation = readStorage("boardRotation");
  if (settings.boardRotation === null) {
    settings.boardRotation = config.board_rotation * 5;
  } else {
    settings.boardRotation = parseInt(settings.boardRotation);
  }
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
}

///////////////////////////////////////////////

///////////////////////////////////////////////
/* PCB rendering code */

var emptyContext2d = document.createElement("canvas").getContext("2d");

function deg2rad(deg) {
  return deg * Math.PI / 180;
}

function calcFontPoint(linepoint, text, offsetx, offsety, tilt) {
  var point = [
    linepoint[0] * text.width + offsetx,
    linepoint[1] * text.height + offsety
  ];
  // Adding half a line height here is technically a bug
  // but pcbnew currently does the same, text is slightly shifted.
  point[0] -= (point[1] + text.height * 0.5) * tilt;
  return point;
}

function drawtext(ctx, text, color, flip) {
  if ("ref" in text && !settings.renderReferences) return;
  if ("val" in text && !settings.renderValues) return;
  ctx.save();
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  ctx.lineJoin = "round";
  ctx.lineWidth = text.thickness;
  if (text.svgpath) {
    ctx.stroke(new Path2D(text.svgpath));
    ctx.restore();
    return;
  }
  ctx.translate(...text.pos);
  var angle = -text.angle;
  if (text.attr.includes("mirrored")) {
    ctx.scale(-1, 1);
    angle = -angle;
  }
  var tilt = 0;
  if (text.attr.includes("italic")) {
    tilt = 0.125;
  }
  var interline = (text.height * 1.5 + text.thickness) / 2;
  var txt = text.text.split("\n");
  // KiCad ignores last empty line.
  if (txt[txt.length - 1] == '') txt.pop();
  ctx.rotate(deg2rad(angle));
  for (var i in txt) {
    var offsety = (-(txt.length - 1) + i * 2) * interline + text.height / 2;
    var lineWidth = 0;
    for (var c of txt[i]) {
      if (c == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        lineWidth += fourSpaces - lineWidth % fourSpaces;
      } else {
        lineWidth += pcbdata.font_data[c].w * text.width;
      }
    }
    var offsetx = 0;
    switch (text.horiz_justify) {
      case -1:
        // Justify left, do nothing
        break;
      case 0:
        // Justify center
        offsetx -= lineWidth / 2;
        break;
      case 1:
        // Justify right
        offsetx -= lineWidth;
        break;
    }
    for (var c of txt[i]) {
      if (c == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        offsetx += fourSpaces - offsetx % fourSpaces;
        continue;
      }
      for (var line of pcbdata.font_data[c].l) {
        ctx.beginPath();
        ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
        for (var i = 1; i < line.length; i++) {
          ctx.lineTo(...calcFontPoint(line[i], text, offsetx, offsety, tilt));
        }
        ctx.stroke();
      }
      offsetx += pcbdata.font_data[c].w * text.width;
    }
  }
  ctx.restore();
}

function drawedge(ctx, scalefactor, edge, color) {
  ctx.strokeStyle = color;
  ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
  ctx.lineCap = "round";
  if (edge.svgpath) {
    ctx.stroke(new Path2D(edge.svgpath));
  } else {
    ctx.beginPath();
    if (edge.type == "segment") {
      ctx.moveTo(...edge.start);
      ctx.lineTo(...edge.end);
    }
    if (edge.type == "arc") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        deg2rad(edge.startangle),
        deg2rad(edge.endangle));
    }
    if (edge.type == "circle") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        0, 2 * Math.PI);
      ctx.closePath();
    }
    if (edge.type == "curve") {
      ctx.moveTo(...edge.start);
      ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
    }
    ctx.stroke();
  }
}

function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
  // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
  var path = new Path2D();
  var width = size[0];
  var height = size[1];
  var x = width * -0.5;
  var y = height * -0.5;
  var chamfOffset = Math.min(width, height) * chamfratio;
  path.moveTo(x, 0);
  if (chamfpos & 4) {
    path.lineTo(x, y + height - chamfOffset);
    path.lineTo(x + chamfOffset, y + height);
    path.lineTo(0, y + height);
  } else {
    path.arcTo(x, y + height, x + width, y + height, radius);
  }
  if (chamfpos & 8) {
    path.lineTo(x + width - chamfOffset, y + height);
    path.lineTo(x + width, y + height - chamfOffset);
    path.lineTo(x + width, 0);
  } else {
    path.arcTo(x + width, y + height, x + width, y, radius);
  }
  if (chamfpos & 2) {
    path.lineTo(x + width, y + chamfOffset);
    path.lineTo(x + width - chamfOffset, y);
    path.lineTo(0, y);
  } else {
    path.arcTo(x + width, y, x, y, radius);
  }
  if (chamfpos & 1) {
    path.lineTo(x + chamfOffset, y);
    path.lineTo(x, y + chamfOffset);
    path.lineTo(x, 0);
  } else {
    path.arcTo(x, y, x, y + height, radius);
  }
  path.closePath();
  return path;
}

function getOblongPath(size) {
  return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
}

function getPolygonsPath(shape) {
  if (shape.path2d) {
    return shape.path2d;
  }
  if (shape.svgpath) {
    shape.path2d = new Path2D(shape.svgpath);
  } else {
    var path = new Path2D();
    for (var polygon of shape.polygons) {
      path.moveTo(...polygon[0]);
      for (var i = 1; i < polygon.length; i++) {
        path.lineTo(...polygon[i]);
      }
      path.closePath();
    }
    shape.path2d = path;
  }
  return shape.path2d;
}

function drawPolygonShape(ctx, shape, color) {
  ctx.save();
  ctx.fillStyle = color;
  if (!shape.svgpath) {
    ctx.translate(...shape.pos);
    ctx.rotate(deg2rad(-shape.angle));
  }
  ctx.fill(getPolygonsPath(shape));
  ctx.restore();
}

function drawDrawing(ctx, layer, scalefactor, drawing, color) {
  if (["segment", "arc", "circle", "curve"].includes(drawing.type)) {
    drawedge(ctx, scalefactor, drawing, color);
  } else if (drawing.type == "polygon") {
    drawPolygonShape(ctx, drawing, color);
  } else {
    drawtext(ctx, drawing, color, layer == "B");
  }
}

function getCirclePath(radius) {
  var path = new Path2D();
  path.arc(0, 0, radius, 0, 2 * Math.PI);
  path.closePath();
  return path;
}

function getCachedPadPath(pad) {
  if (!pad.path2d) {
    // if path2d is not set, build one and cache it on pad object
    if (pad.shape == "rect") {
      pad.path2d = new Path2D();
      pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
    } else if (pad.shape == "oval") {
      pad.path2d = getOblongPath(pad.size);
    } else if (pad.shape == "circle") {
      pad.path2d = getCirclePath(pad.size[0] / 2);
    } else if (pad.shape == "roundrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
    } else if (pad.shape == "chamfrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
    } else if (pad.shape == "custom") {
      pad.path2d = getPolygonsPath(pad);
    }
  }
  return pad.path2d;
}

function drawPad(ctx, pad, color, outline, hole) {
  ctx.save();
  ctx.translate(...pad.pos);
  ctx.rotate(deg2rad(pad.angle));
  if (pad.offset) {
    ctx.translate(...pad.offset);
  }
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  var path = getCachedPadPath(pad);
  if (outline) {
    ctx.stroke(path);
  } else {
    ctx.fill(path);
  }
  if (pad.type == "th" && hole) {
    if (pad.offset) {
      ctx.translate(-pad.offset[0], -pad.offset[1]);
    }
    ctx.fillStyle = "#CCCCCC";
    if (pad.drillshape == "oblong") {
      ctx.fill(getOblongPath(pad.drillsize));
    } else {
      ctx.fill(getCirclePath(pad.drillsize[0] / 2));
    }
  }
  ctx.restore();
}

function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, highlight, outline) {
  if (highlight) {
    // draw bounding box
    if (module.layer == layer) {
      ctx.save();
      ctx.globalAlpha = 0.2;
      ctx.translate(...module.bbox.pos);
      ctx.rotate(deg2rad(-module.bbox.angle));
      ctx.translate(...module.bbox.relpos);
      ctx.fillStyle = padcolor;
      ctx.fillRect(0, 0, ...module.bbox.size);
      ctx.globalAlpha = 1;
      ctx.strokeStyle = padcolor;
      ctx.strokeRect(0, 0, ...module.bbox.size);
      ctx.restore();
    }
  }
  // draw drawings
  for (var drawing of module.drawings) {
    if (drawing.layer == layer) {
      drawDrawing(ctx, layer, scalefactor, drawing.drawing, padcolor);
    }
  }
  // draw pads
  if (settings.renderPads) {
    for (var pad of module.pads) {
      if (pad.layers.includes(layer)) {
        drawPad(ctx, pad, padcolor, outline, true);
        if (pad.pin1 && settings.highlightpin1) {
          drawPad(ctx, pad, outlinecolor, true, false);
        }
      }
    }
  }
}

function drawEdgeCuts(canvas, scalefactor) {
  var ctx = canvas.getContext("2d");
  var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color');
  for (var edge of pcbdata.edges) {
    drawedge(ctx, scalefactor, edge, edgecolor);
  }
}

function drawModules(canvas, layer, scalefactor, highlight) {
  var ctx = canvas.getContext("2d");
  ctx.lineWidth = 3 / scalefactor;
  var style = getComputedStyle(topmostdiv);
  var padcolor = style.getPropertyValue('--pad-color');
  var outlinecolor = style.getPropertyValue('--pin1-outline-color');
  if (highlight) {
    padcolor = style.getPropertyValue('--pad-color-highlight');
    outlinecolor = style.getPropertyValue('--pin1-outline-color-highlight');
  }
  for (var i = 0; i < pcbdata.modules.length; i++) {
    var mod = pcbdata.modules[i];
    var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i);
    if (!highlight || highlightedModules.includes(i)) {
      drawModule(ctx, layer, scalefactor, mod, padcolor, outlinecolor, highlight, outline);
    }
  }
}

function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) {
  var ctx = canvas.getContext("2d");
  for (var d of pcbdata[layername][layer]) {
    if (["segment", "arc", "circle", "curve"].includes(d.type)) {
      drawedge(ctx, scalefactor, d, edgeColor);
    } else if (d.type == "polygon") {
      drawPolygonShape(ctx, d, polygonColor);
    } else {
      drawtext(ctx, d, textColor, layer == "B");
    }
  }
}

function drawTracks(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  for(var track of pcbdata.tracks[layer]) {
    if (highlight && highlightedNet != track.net) continue;
    ctx.lineWidth = track.width;
    ctx.beginPath();
    ctx.moveTo(...track.start);
    ctx.lineTo(...track.end);
    ctx.stroke();
  }
}

function drawZones(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
  ctx.lineJoin = "round";
  for(var zone of pcbdata.zones[layer]) {
    if (!zone.path2d) {
      zone.path2d = getPolygonsPath(zone);
    }
    if (highlight && highlightedNet != zone.net) continue;
    ctx.lineWidth = zone.width ? zone.width : 0;
    ctx.fill(zone.path2d);
    ctx.stroke(zone.path2d);
  }
}

function clearCanvas(canvas, color = null) {
  var ctx = canvas.getContext("2d");
  ctx.save();
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  if (color) {
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  } else {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  }
  ctx.restore();
}

function drawNets(canvas, layer, highlight) {
  var style = getComputedStyle(topmostdiv);
  if (settings.renderTracks) {
    var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
    drawTracks(canvas, layer, trackColor, highlight);
  }
  if (settings.renderZones) {
    var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
    drawZones(canvas, layer, zoneColor, highlight);
  }
  if (highlight && settings.renderPads) {
    var padColor = style.getPropertyValue('--pad-color-highlight');
    var ctx = canvas.getContext("2d");
    for (var mod of pcbdata.modules) {
      // draw pads
      for (var pad of mod.pads) {
        if (highlightedNet != pad.net) continue;
        if (pad.layers.includes(layer)) {
          drawPad(ctx, pad, padColor, false, true);
        }
      }
    }
  }
}

function drawHighlightsOnLayer(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.highlight);
  }
  if (highlightedModules.length > 0) {
    drawModules(canvasdict.highlight, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom, true);
  }
  if (highlightedNet !== null) {
    drawNets(canvasdict.highlight, canvasdict.layer, true);
  }
}

function drawHighlights() {
  drawHighlightsOnLayer(allcanvas.front);
  drawHighlightsOnLayer(allcanvas.back);
}

function drawBackground(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.bg);
    clearCanvas(canvasdict.fab);
    clearCanvas(canvasdict.silk);
  }

  drawNets(canvasdict.bg, canvasdict.layer, false);
  drawModules(canvasdict.bg, canvasdict.layer,
    canvasdict.transform.s * canvasdict.transform.zoom, false);

  drawEdgeCuts(canvasdict.bg, canvasdict.transform.s);

  var style = getComputedStyle(topmostdiv);
  var edgeColor = style.getPropertyValue('--silkscreen-edge-color');
  var polygonColor = style.getPropertyValue('--silkscreen-polygon-color');
  var textColor = style.getPropertyValue('--silkscreen-text-color');
  if (settings.renderSilkscreen) {
    drawBgLayer(
      "silkscreen", canvasdict.silk, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
  edgeColor = style.getPropertyValue('--fabrication-edge-color');
  polygonColor = style.getPropertyValue('--fabrication-polygon-color');
  textColor = style.getPropertyValue('--fabrication-text-color');
  if (settings.renderFabrication) {
    drawBgLayer(
      "fabrication", canvasdict.fab, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
}

function prepareCanvas(canvas, flip, transform) {
  var ctx = canvas.getContext("2d");
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  var fontsize = 1.55;
  ctx.scale(transform.zoom, transform.zoom);
  ctx.translate(transform.panx, transform.pany);
  if (flip) {
    ctx.scale(-1, 1);
  }
  ctx.translate(transform.x, transform.y);
  ctx.rotate(deg2rad(settings.boardRotation));
  ctx.scale(transform.s, transform.s);
}

function prepareLayer(canvasdict) {
  var flip = (canvasdict.layer == "B");
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    prepareCanvas(canvasdict[c], flip, canvasdict.transform);
  }
}

function rotateVector(v, angle) {
  angle = deg2rad(angle);
  return [
    v[0] * Math.cos(angle) - v[1] * Math.sin(angle),
    v[0] * Math.sin(angle) + v[1] * Math.cos(angle)
  ];
}

function applyRotation(bbox) {
  var corners = [
    [bbox.minx, bbox.miny],
    [bbox.minx, bbox.maxy],
    [bbox.maxx, bbox.miny],
    [bbox.maxx, bbox.maxy],
  ];
  corners = corners.map((v) => rotateVector(v, settings.boardRotation));
  return {
    minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity),
    miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity),
    maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity),
    maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity),
  }
}

function recalcLayerScale(layerdict, width, height) {
  var bbox = applyRotation(pcbdata.edges_bbox);
  var scalefactor = 0.98 * Math.min(
    width / (bbox.maxx - bbox.minx),
    height / (bbox.maxy - bbox.miny)
  );
  if (scalefactor < 0.1) {
    scalefactor = 1;
  }
  layerdict.transform.s = scalefactor;
  var flip = (layerdict.layer == "B");
  if (flip) {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5;
  } else {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5;
  }
  layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5;
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    canvas = layerdict[c];
    canvas.width = width;
    canvas.height = height;
    canvas.style.width = (width / devicePixelRatio) + "px";
    canvas.style.height = (height / devicePixelRatio) + "px";
  }
}

function redrawCanvas(layerdict) {
  prepareLayer(layerdict);
  drawBackground(layerdict);
  drawHighlightsOnLayer(layerdict);
}

function resizeCanvas(layerdict) {
  var canvasdivid = {
    "F": "frontcanvas",
    "B": "backcanvas"
  } [layerdict.layer];
  var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio;
  var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio;
  recalcLayerScale(layerdict, width, height);
  redrawCanvas(layerdict);
}

function resizeAll() {
  resizeCanvas(allcanvas.front);
  resizeCanvas(allcanvas.back);
}

function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) {
  var A = x - x1;
  var B = y - y1;
  var C = x2 - x1;
  var D = y2 - y1;

  var dot = A * C + B * D;
  var len_sq = C * C + D * D;
  var dx, dy;
  if (len_sq == 0) {
    // start and end of the segment coincide
    dx = x - x1;
    dy = y - y1;
  } else {
    var param = dot / len_sq;
    var xx, yy;
    if (param < 0) {
      xx = x1;
      yy = y1;
    } else if (param > 1) {
      xx = x2;
      yy = y2;
    } else {
      xx = x1 + param * C;
      yy = y1 + param * D;
    }
    dx = x - xx;
    dy = y - yy;
  }
  return dx * dx + dy * dy <= d * d;
}

function pointWithinPad(x, y, pad) {
  var v = [x - pad.pos[0], y - pad.pos[1]];
  v = rotateVector(v, -pad.angle);
  if (pad.offset) {
    v[0] -= pad.offset[0];
    v[1] -= pad.offset[1];
  }
  return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v);
}

function netHitScan(layer, x, y) {
  // Check track segments
  if (settings.renderTracks && pcbdata.tracks) {
    for(var track of pcbdata.tracks[layer]) {
      if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) {
        return track.net;
      }
    }
  }
  // Check pads
  if (settings.renderPads) {
    for (var mod of pcbdata.modules) {
      for(var pad of mod.pads) {
        if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
          return pad.net;
        }
      }
    }
  }
  return null;
}

function pointWithinModuleBbox(x, y, bbox) {
  var v = [x - bbox.pos[0], y - bbox.pos[1]];
  v = rotateVector(v, bbox.angle);
  return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] &&
         bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1];
}

function bboxHitScan(layer, x, y) {
  var result = [];
  for (var i = 0; i < pcbdata.modules.length; i++) {
    var module = pcbdata.modules[i];
    if (module.layer == layer) {
      if (pointWithinModuleBbox(x, y, module.bbox)) {
        result.push(i);
      }
    }
  }
  return result;
}

function handlePointerDown(e, layerdict) {
  if (e.button != 0) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  layerdict.pointerStates[e.pointerId] = {
    distanceTravelled: 0,
    lastX: e.offsetX,
    lastY: e.offsetY,
    downTime: Date.now(),
  };
}

function handleMouseClick(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var x = e.offsetX;
  var y = e.offsetY;
  var t = layerdict.transform;
  if (layerdict.layer == "B") {
    x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s;
  } else {
    x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s;
  }
  y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s;
  var v = rotateVector([x, y], -settings.boardRotation);
  if ("nets" in pcbdata) {
    var net = netHitScan(layerdict.layer, ...v);
    if (net !== highlightedNet) {
      netClicked(net);
    }
  }
  if (highlightedNet === null) {
    var modules = bboxHitScan(layerdict.layer, ...v);
    if (modules.length > 0) {
      modulesClicked(modules);
    }
  }
}

function handlePointerLeave(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();

  if (!settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }

  delete layerdict.pointerStates[e.pointerId];
}

function resetTransform(layerdict) {
  layerdict.transform.panx = 0;
  layerdict.transform.pany = 0;
  layerdict.transform.zoom = 1;
  redrawCanvas(layerdict);
}

function handlePointerUp(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  e.preventDefault();
  e.stopPropagation();

  if (e.button == 2) {
    // Reset pan and zoom on right click.
    resetTransform(layerdict);
    layerdict.anotherPointerTapped = false;
    return;
  }

  // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now
  var ptr = layerdict.pointerStates[e.pointerId];
  ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY);

  if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) {
    if (Object.keys(layerdict.pointerStates).length == 1) {
      if (layerdict.anotherPointerTapped) {
        // This is the second pointer coming off of a two-finger tap
        resetTransform(layerdict);
      } else {
        // This is just a regular tap
        handleMouseClick(e, layerdict);
      }
      layerdict.anotherPointerTapped = false;
    } else {
      // This is the first finger coming off of what could become a two-finger tap
      layerdict.anotherPointerTapped = true;
    }
  } else {
    if (!settings.redrawOnDrag) {
      redrawCanvas(layerdict);
    }
    layerdict.anotherPointerTapped = false;
  }

  delete layerdict.pointerStates[e.pointerId];
}

function handlePointerMove(e, layerdict) {
  if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var thisPtr = layerdict.pointerStates[e.pointerId];

  var dx = e.offsetX - thisPtr.lastX;
  var dy = e.offsetY - thisPtr.lastY;

  // If this number is low on pointer up, we count the action as a click
  thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy);

  if (Object.keys(layerdict.pointerStates).length == 1) {
    // This is a simple drag
    layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom;
    layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom;
  } else if (Object.keys(layerdict.pointerStates).length == 2) {
    var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0];

    var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2));
    var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2)     + Math.pow(e.offsetY - otherPtr.lastY, 2));

    var scaleFactor = newDist/oldDist;

    if (scaleFactor != NaN) {
      layerdict.transform.zoom *= scaleFactor;

      var zoomd = (1 - scaleFactor) / layerdict.transform.zoom;
      layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd;
      layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd;
    }
  }

  thisPtr.lastX = e.offsetX;
  thisPtr.lastY = e.offsetY;

  if (settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }
}

function handleMouseWheel(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();
  var t = layerdict.transform;
  var wheeldelta = e.deltaY;
  if (e.deltaMode == 1) {
    // FF only, scroll by lines
    wheeldelta *= 30;
  } else if (e.deltaMode == 2) {
    wheeldelta *= 300;
  }
  var m = Math.pow(1.1, -wheeldelta / 40);
  // Limit amount of zoom per tick.
  if (m > 2) {
    m = 2;
  } else if (m < 0.5) {
    m = 0.5;
  }
  t.zoom *= m;
  var zoomd = (1 - m) / t.zoom;
  t.panx += devicePixelRatio * e.offsetX * zoomd;
  t.pany += devicePixelRatio * e.offsetY * zoomd;
  redrawCanvas(layerdict);
}

function addMouseHandlers(div, layerdict) {
  div.addEventListener("pointerdown", function(e) {
    handlePointerDown(e, layerdict);
  });
  div.addEventListener("pointermove", function(e) {
    handlePointerMove(e, layerdict);
  });
  div.addEventListener("pointerup", function(e) {
    handlePointerUp(e, layerdict);
  });
  var pointerleave = function(e) {
    handlePointerLeave(e, layerdict);
  }
  div.addEventListener("pointercancel", pointerleave);
  div.addEventListener("pointerleave", pointerleave);
  div.addEventListener("pointerout", pointerleave);

  div.onwheel = function(e) {
    handleMouseWheel(e, layerdict);
  }
  for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) {
    element.addEventListener("contextmenu", function(e) {
      e.preventDefault();
    }, false);
  }
}

function setRedrawOnDrag(value) {
  settings.redrawOnDrag = value;
  writeStorage("redrawOnDrag", value);
}

function setBoardRotation(value) {
  settings.boardRotation = value * 5;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  resizeAll();
}

function initRender() {
  allcanvas = {
    front: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("F_bg"),
      fab: document.getElementById("F_fab"),
      silk: document.getElementById("F_slk"),
      highlight: document.getElementById("F_hl"),
      layer: "F",
    },
    back: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("B_bg"),
      fab: document.getElementById("B_fab"),
      silk: document.getElementById("B_slk"),
      highlight: document.getElementById("B_hl"),
      layer: "B",
    }
  };
  addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front);
  addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back);
}

///////////////////////////////////////////////

///////////////////////////////////////////////
/* DOM manipulation and misc code */

var bomsplit;
var canvassplit;
var initDone = false;
var bomSortFunction = null;
var currentSortColumn = null;
var currentSortOrder = null;
var currentHighlightedRowId;
var highlightHandlers = [];
var moduleIndexToHandler = {};
var netsToHandler = {};
var highlightedModules = [];
var highlightedNet = null;
var lastClicked;

function dbg(html) {
  dbgdiv.innerHTML = html;
}

function redrawIfInitDone() {
  if (initDone) {
    redrawCanvas(allcanvas.front);
    redrawCanvas(allcanvas.back);
  }
}

function padsVisible(value) {
  writeStorage("padsVisible", value);
  settings.renderPads = value;
  redrawIfInitDone();
}

function referencesVisible(value) {
  writeStorage("referencesVisible", value);
  settings.renderReferences = value;
  redrawIfInitDone();
}

function valuesVisible(value) {
  writeStorage("valuesVisible", value);
  settings.renderValues = value;
  redrawIfInitDone();
}

function tracksVisible(value) {
  writeStorage("tracksVisible", value);
  settings.renderTracks = value;
  redrawIfInitDone();
}

function zonesVisible(value) {
  writeStorage("zonesVisible", value);
  settings.renderZones = value;
  redrawIfInitDone();
}

function dnpOutline(value) {
  writeStorage("dnpOutline", value);
  settings.renderDnpOutline = value;
  redrawIfInitDone();
}

function setDarkMode(value) {
  if (value) {
    topmostdiv.classList.add("dark");
  } else {
    topmostdiv.classList.remove("dark");
  }
  writeStorage("darkmode", value);
  settings.darkMode = value;
  redrawIfInitDone();
}

function setFullscreen(value) {
  if (value) {
    document.documentElement.requestFullscreen();
  } else {
    document.exitFullscreen();
  }
}

function fabricationVisible(value) {
  writeStorage("fabricationVisible", value);
  settings.renderFabrication = value;
  redrawIfInitDone();
}

function silkscreenVisible(value) {
  writeStorage("silkscreenVisible", value);
  settings.renderSilkscreen = value;
  redrawIfInitDone();
}

function setHighlightPin1(value) {
  writeStorage("highlightpin1", value);
  settings.highlightpin1 = value;
  redrawIfInitDone();
}

function getStoredCheckboxRefs(checkbox) {
  function convert(ref) {
    var intref = parseInt(ref);
    if (isNaN(intref)) {
      for (var i = 0; i < pcbdata.modules.length; i++) {
        if (pcbdata.modules[i].ref == ref) {
          return i;
        }
      }
      return -1;
    } else {
      return intref;
    }
  }
  if (!(checkbox in settings.checkboxStoredRefs)) {
    var val = readStorage("checkbox_" + checkbox);
    settings.checkboxStoredRefs[checkbox] = val ? val : "";
  }
  if (!settings.checkboxStoredRefs[checkbox]) {
    return new Set();
  } else {
    return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
  }
}

function getCheckboxState(checkbox, references) {
  var storedRefsSet = getStoredCheckboxRefs(checkbox);
  var currentRefsSet = new Set(references.map(r => r[1]));
  // Get difference of current - stored
  var difference = new Set(currentRefsSet);
  for (ref of storedRefsSet) {
    difference.delete(ref);
  }
  if (difference.size == 0) {
    // All the current refs are stored
    return "checked";
  } else if (difference.size == currentRefsSet.size) {
    // None of the current refs are stored
    return "unchecked";
  } else {
    // Some of the refs are stored
    return "indeterminate";
  }
}

function setBomCheckboxState(checkbox, element, references) {
  var state = getCheckboxState(checkbox, references);
  element.checked = (state == "checked");
  element.indeterminate = (state == "indeterminate");
}

function createCheckboxChangeHandler(checkbox, references) {
  return function(evt) {
    refsSet = getStoredCheckboxRefs(checkbox);
    var darkenWhenChecked = settings.darkenWhenChecked == checkbox;
    if (this.checked) {
      // checkbox ticked
      for (var ref of references) {
        refsSet.add(ref[1]);
      }
      if (darkenWhenChecked) {
        evt.target.parentElement.parentElement.classList.add("checked");
      }
    } else {
      // checkbox unticked
      for (var ref of references) {
        refsSet.delete(ref[1]);
      }
      if (darkenWhenChecked) {
        evt.target.parentElement.parentElement.classList.remove("checked");
      }
    }
    settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
    updateCheckboxStats(checkbox);
  }
}

function clearHighlightedModules() {
  if (currentHighlightedRowId) {
    document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    currentHighlightedRowId = null;
    highlightedModules = [];
    highlightedNet = null;
  }
}

function createRowHighlightHandler(rowid, refs, net) {
  return function() {
    if (currentHighlightedRowId) {
      if (currentHighlightedRowId == rowid) {
        return;
      }
      document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    }
    document.getElementById(rowid).classList.add("highlighted");
    currentHighlightedRowId = rowid;
    highlightedModules = refs ? refs.map(r => r[1]) : [];
    highlightedNet = net;
    drawHighlights();
  }
}

function entryMatches(entry) {
  if (settings.bommode == "netlist") {
    // entry is just a net name
    return entry.toLowerCase().indexOf(filter) >= 0;
  }
  // check refs
  for (var ref of entry[3]) {
    if (ref[0].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check extra fields
  for (var i in config.extra_fields) {
    if (entry[4][i].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check value
  if (entry[1].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  // check footprint
  if (entry[2].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  return false;
}

function findRefInEntry(entry) {
  return entry[3].filter(r => r[0].toLowerCase() == reflookup);
}

function highlightFilter(s) {
  if (!filter) {
    return s;
  }
  var parts = s.toLowerCase().split(filter);
  if (parts.length == 1) {
    return s;
  }
  var r = "";
  var pos = 0;
  for (var i in parts) {
    if (i > 0) {
      r += '<mark class="highlight">' +
        s.substring(pos, pos + filter.length) +
        '</mark>';
      pos += filter.length;
    }
    r += s.substring(pos, pos + parts[i].length);
    pos += parts[i].length;
  }
  return r;
}

function checkboxSetUnsetAllHandler(checkboxname) {
  return function() {
    var checkboxnum = 0;
    while (checkboxnum < settings.checkboxes.length &&
      settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
      checkboxnum++;
    }
    if (checkboxnum >= settings.checkboxes.length) {
      return;
    }
    var allset = true;
    var checkbox;
    var row;
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      if (!checkbox.checked || checkbox.indeterminate) {
        allset = false;
        break;
      }
    }
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      checkbox.checked = !allset;
      checkbox.indeterminate = false;
      checkbox.onchange();
    }
  }
}

function createColumnHeader(name, cls, comparator) {
  var th = document.createElement("TH");
  th.innerHTML = name;
  th.classList.add(cls);
  th.style.cursor = "pointer";
  var span = document.createElement("SPAN");
  span.classList.add("sortmark");
  span.classList.add("none");
  th.appendChild(span);
  th.onclick = function() {
    if (currentSortColumn && this !== currentSortColumn) {
      // Currently sorted by another column
      currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
      currentSortColumn.childNodes[1].classList.add("none");
      currentSortColumn = null;
      currentSortOrder = null;
    }
    if (currentSortColumn && this === currentSortColumn) {
      // Already sorted by this column
      if (currentSortOrder == "asc") {
        // Sort by this column, descending order
        bomSortFunction = function(a, b) {
          return -comparator(a, b);
        }
        currentSortColumn.childNodes[1].classList.remove("asc");
        currentSortColumn.childNodes[1].classList.add("desc");
        currentSortOrder = "desc";
      } else {
        // Unsort
        bomSortFunction = null;
        currentSortColumn.childNodes[1].classList.remove("desc");
        currentSortColumn.childNodes[1].classList.add("none");
        currentSortColumn = null;
        currentSortOrder = null;
      }
    } else {
      // Sort by this column, ascending order
      bomSortFunction = comparator;
      currentSortColumn = this;
      currentSortColumn.childNodes[1].classList.remove("none");
      currentSortColumn.childNodes[1].classList.add("asc");
      currentSortOrder = "asc";
    }
    populateBomBody();
  }
  return th;
}

function populateBomHeader() {
  while (bomhead.firstChild) {
    bomhead.removeChild(bomhead.firstChild);
  }
  var tr = document.createElement("TR");
  var th = document.createElement("TH");
  th.classList.add("numCol");
  tr.appendChild(th);
  var checkboxCompareClosure = function(checkbox) {
    return (a, b) => {
      var stateA = getCheckboxState(checkbox, a[3]);
      var stateB = getCheckboxState(checkbox, b[3]);
      if (stateA > stateB) return -1;
      if (stateA < stateB) return 1;
      return 0;
    }
  }
  if (settings.bommode == "netlist") {
    th = createColumnHeader("Net name", "bom-netname", (a, b) => {
      if (a > b) return -1;
      if (a < b) return 1;
      return 0;
    });
    tr.appendChild(th);
  } else {
    for (var checkbox of settings.checkboxes) {
      th = createColumnHeader(
        checkbox, "bom-checkbox", checkboxCompareClosure(checkbox));
      th.onclick = fancyDblClickHandler(
        th, th.onclick.bind(th), checkboxSetUnsetAllHandler(checkbox));
      tr.appendChild(th);
    }
    tr.appendChild(createColumnHeader("References", "References", (a, b) => {
      var i = 0;
      while (i < a[3].length && i < b[3].length) {
        if (a[3][i] != b[3][i]) return a[3][i] > b[3][i] ? 1 : -1;
        i++;
      }
      return a[3].length - b[3].length;
    }));
    // Extra fields
    if (config.extra_fields.length > 0) {
      var extraFieldCompareClosure = function(fieldIndex) {
        return (a, b) => {
          var fa = a[4][fieldIndex];
          var fb = b[4][fieldIndex];
          if (fa != fb) return fa > fb ? 1 : -1;
          else return 0;
        }
      }
      for (var i in config.extra_fields) {
        tr.appendChild(createColumnHeader(
          config.extra_fields[i], "extra", extraFieldCompareClosure(i)));
      }
    }
    tr.appendChild(createColumnHeader("Value", "Value", (a, b) => {
      return valueCompare(a[5], b[5], a[1], b[1]);
    }));
    tr.appendChild(createColumnHeader("Footprint", "Footprint", (a, b) => {
      if (a[2] != b[2]) return a[2] > b[2] ? 1 : -1;
      else return 0;
    }));
    if (settings.bommode == "grouped") {
      tr.appendChild(createColumnHeader("Quantity", "Quantity", (a, b) => {
        return a[3].length - b[3].length;
      }));
    }
  }
  bomhead.appendChild(tr);
}

function populateBomBody() {
  while (bom.firstChild) {
    bom.removeChild(bom.firstChild);
  }
  highlightHandlers = [];
  moduleIndexToHandler = {};
  netsToHandler = {};
  currentHighlightedRowId = null;
  var first = true;
  if (settings.bommode == "netlist") {
    bomtable = pcbdata.nets.slice();
  } else {
    switch (settings.canvaslayout) {
      case 'F':
        bomtable = pcbdata.bom.F.slice();
        break;
      case 'FB':
        bomtable = pcbdata.bom.both.slice();
        break;
      case 'B':
        bomtable = pcbdata.bom.B.slice();
        break;
    }
    if (settings.bommode == "ungrouped") {
      // expand bom table
      expandedTable = []
      for (var bomentry of bomtable) {
        for (var ref of bomentry[3]) {
          expandedTable.push([1, bomentry[1], bomentry[2], [ref], bomentry[4], bomentry[5]]);
        }
      }
      bomtable = expandedTable;
    }
  }
  if (bomSortFunction) {
    bomtable = bomtable.sort(bomSortFunction);
  }
  for (var i in bomtable) {
    var bomentry = bomtable[i];
    if (filter && !entryMatches(bomentry)) {
      continue;
    }
    var references = null;
    var netname = null;
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    var rownum = +i + 1;
    tr.id = "bomrow" + rownum;
    td.textContent = rownum;
    tr.appendChild(td);
    if (settings.bommode == "netlist") {
      netname = bomentry;
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(netname ? netname : "&lt;no net&gt;");
      tr.appendChild(td);
    } else {
      if (reflookup) {
        references = findRefInEntry(bomentry);
        if (references.length == 0) {
          continue;
        }
      } else {
        references = bomentry[3];
      }
      // Checkboxes
      for (var checkbox of settings.checkboxes) {
        if (checkbox) {
          td = document.createElement("TD");
          var input = document.createElement("input");
          input.type = "checkbox";
          input.onchange = createCheckboxChangeHandler(checkbox, references);
          setBomCheckboxState(checkbox, input, references);
          if (input.checked && settings.darkenWhenChecked == checkbox) {
            tr.classList.add("checked");
          }
          td.appendChild(input);
          tr.appendChild(td);
        }
      }
      // References
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
      tr.appendChild(td);
      // Extra fields
      for (var i in config.extra_fields) {
        td = document.createElement("TD");
        td.innerHTML = highlightFilter(bomentry[4][i]);
        tr.appendChild(td);
      }
      // Value
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[1]);
      tr.appendChild(td);
      // Footprint
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[2]);
      tr.appendChild(td);
      if (settings.bommode == "grouped") {
        // Quantity
        td = document.createElement("TD");
        td.textContent = bomentry[3].length;
        tr.appendChild(td);
      }
    }
    bom.appendChild(tr);
    var handler = createRowHighlightHandler(tr.id, references, netname);
    tr.onmousemove = handler;
    highlightHandlers.push({
      id: tr.id,
      handler: handler,
    });
    if (references !== null) {
      for (var refIndex of references.map(r => r[1])) {
        moduleIndexToHandler[refIndex] = handler;
      }
    }
    if (netname !== null) {
      netsToHandler[netname] = handler;
    }
    if ((filter || reflookup) && first) {
      handler();
      first = false;
    }
  }
}

function highlightPreviousRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[highlightHandlers.length - 1].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[0].id == currentHighlightedRowId) {
      highlightHandlers[highlightHandlers.length - 1].handler();
    } else {
      for (var i = 0; i < highlightHandlers.length - 1; i++) {
        if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function highlightNextRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[0].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
      highlightHandlers[0].handler();
    } else {
      for (var i = 1; i < highlightHandlers.length; i++) {
        if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function populateBomTable() {
  populateBomHeader();
  populateBomBody();
}

function modulesClicked(moduleIndexes) {
  var lastClickedIndex = moduleIndexes.indexOf(lastClicked);
  for (var i = 1; i <= moduleIndexes.length; i++) {
    var refIndex = moduleIndexes[(lastClickedIndex + i) % moduleIndexes.length];
    if (refIndex in moduleIndexToHandler) {
      lastClicked = refIndex;
      moduleIndexToHandler[refIndex]();
      smoothScrollToRow(currentHighlightedRowId);
      break;
    }
  }
}

function netClicked(net) {
  if (net in netsToHandler) {
    netsToHandler[net]();
    smoothScrollToRow(currentHighlightedRowId);
  } else {
    clearHighlightedModules();
    highlightedNet = net;
    drawHighlights();
  }
}

function updateFilter(input) {
  filter = input.toLowerCase();
  populateBomTable();
}

function updateRefLookup(input) {
  reflookup = input.toLowerCase();
  populateBomTable();
}

function changeCanvasLayout(layout) {
  document.getElementById("fl-btn").classList.remove("depressed");
  document.getElementById("fb-btn").classList.remove("depressed");
  document.getElementById("bl-btn").classList.remove("depressed");
  switch (layout) {
    case 'F':
      document.getElementById("fl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(1);
      }
      break;
    case 'B':
      document.getElementById("bl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(0);
      }
      break;
    default:
      document.getElementById("fb-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.setSizes([50, 50]);
      }
  }
  settings.canvaslayout = layout;
  writeStorage("canvaslayout", layout);
  resizeAll();
  changeBomMode(settings.bommode);
}

function populateMetadata() {
  document.getElementById("title").innerHTML = pcbdata.metadata.title;
  document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
  document.getElementById("company").innerHTML = pcbdata.metadata.company;
  document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
  if (pcbdata.metadata.title != "") {
    document.title = pcbdata.metadata.title + " BOM";
  }
  // Calculate board stats
  var fp_f = 0, fp_b = 0, pads_f = 0, pads_b = 0, pads_th = 0;
  for (var i = 0; i < pcbdata.modules.length; i++) {
    if (pcbdata.bom.skipped.includes(i)) continue;
    var mod = pcbdata.modules[i];
    if (mod.layer == "F") {
      fp_f++;
    } else {
      fp_b++;
    }
    for (var pad of mod.pads) {
      if (pad.type == "th") {
        pads_th++;
      } else {
        if (pad.layers.includes("F")) {
          pads_f++;
        }
        if (pad.layers.includes("B")) {
          pads_b++;
        }
      }
    }
  }
  document.getElementById("stats-components-front").innerHTML = fp_f;
  document.getElementById("stats-components-back").innerHTML = fp_b;
  document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
  document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
  document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
  document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
  document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
  document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
  document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
  document.getElementById("stats-th-pads").innerHTML = pads_th;
  // Update version string
  document.getElementById("github-link").innerHTML = "InteractiveHtmlBom&nbsp;" +
    /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0];
}

function changeBomLayout(layout) {
  document.getElementById("bom-btn").classList.remove("depressed");
  document.getElementById("lr-btn").classList.remove("depressed");
  document.getElementById("tb-btn").classList.remove("depressed");
  switch (layout) {
    case 'bom-only':
      document.getElementById("bom-btn").classList.add("depressed");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      document.getElementById("frontcanvas").style.display = "none";
      document.getElementById("backcanvas").style.display = "none";
      document.getElementById("bot").style.height = "";
      break;
    case 'top-bottom':
      document.getElementById("tb-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.remove("split-horizontal");
      document.getElementById("canvasdiv").classList.remove("split-horizontal");
      document.getElementById("frontcanvas").classList.add("split-horizontal");
      document.getElementById("backcanvas").classList.add("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        direction: "vertical",
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        onDragEnd: resizeAll
      });
      break;
    case 'left-right':
      document.getElementById("lr-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.add("split-horizontal");
      document.getElementById("canvasdiv").classList.add("split-horizontal");
      document.getElementById("frontcanvas").classList.remove("split-horizontal");
      document.getElementById("backcanvas").classList.remove("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        direction: "vertical",
        onDragEnd: resizeAll
      });
  }
  settings.bomlayout = layout;
  writeStorage("bomlayout", layout);
  changeCanvasLayout(settings.canvaslayout);
}

function changeBomMode(mode) {
  document.getElementById("bom-grouped-btn").classList.remove("depressed");
  document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
  document.getElementById("bom-netlist-btn").classList.remove("depressed");
  switch (mode) {
    case 'grouped':
      document.getElementById("bom-grouped-btn").classList.add("depressed");
      break;
    case 'ungrouped':
      document.getElementById("bom-ungrouped-btn").classList.add("depressed");
      break;
    case 'netlist':
      document.getElementById("bom-netlist-btn").classList.add("depressed");
  }
  writeStorage("bommode", mode);
  if (mode != settings.bommode) {
    settings.bommode = mode;
    bomSortFunction = null;
    currentSortColumn = null;
    currentSortOrder = null;
    clearHighlightedModules();
  }
  populateBomTable();
}

function focusFilterField() {
  focusInputField(document.getElementById("filter"));
}

function focusRefLookupField() {
  focusInputField(document.getElementById("reflookup"));
}

function toggleBomCheckbox(bomrowid, checkboxnum) {
  if (!bomrowid || checkboxnum > settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum].childNodes[0];
  checkbox.checked = !checkbox.checked;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function checkBomCheckbox(bomrowid, checkboxname) {
  var checkboxnum = 0;
  while (checkboxnum < settings.checkboxes.length &&
    settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
    checkboxnum++;
  }
  if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0];
  checkbox.checked = true;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function setBomCheckboxes(value) {
  writeStorage("bomCheckboxes", value);
  settings.checkboxes = value.split(",").filter((e) => e);
  prepCheckboxes();
  populateBomTable();
  populateDarkenWhenCheckedOptions();
}

function setDarkenWhenChecked(value) {
  writeStorage("darkenWhenChecked", value);
  settings.darkenWhenChecked = value;
  populateBomTable();
}

function prepCheckboxes() {
  var table = document.getElementById("checkbox-stats");
  while (table.childElementCount > 1) {
    table.removeChild(table.lastChild);
  }
  if (settings.checkboxes.length) {
    table.style.display = "";
  } else {
    table.style.display = "none";
  }
  for (var checkbox of settings.checkboxes) {
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    td.innerHTML = checkbox;
    tr.appendChild(td);
    td = document.createElement("TD");
    td.id = "checkbox-stats-" + checkbox;
    var progressbar = document.createElement("div");
    progressbar.classList.add("bar");
    td.appendChild(progressbar);
    var text = document.createElement("div");
    text.classList.add("text");
    td.appendChild(text);
    tr.appendChild(td);
    table.appendChild(tr);
    updateCheckboxStats(checkbox);
  }
}

function populateDarkenWhenCheckedOptions() {
  var container = document.getElementById("darkenWhenCheckedContainer");

  if (settings.checkboxes.length == 0) {
    container.parentElement.style.display = "none";
    return;
  }

  container.innerHTML = '';
  container.parentElement.style.display = "inline-block";
  
  function createOption(name, displayName) {
    var id = "darkenWhenChecked-" + name;

    var div = document.createElement("div");
    div.classList.add("radio-container");

    var input = document.createElement("input");
    input.type = "radio";
    input.name = "darkenWhenChecked";
    input.value = name;
    input.id = id;
    input.onchange = () => setDarkenWhenChecked(name);
    div.appendChild(input);

    // Preserve the selected element when the checkboxes change
    if (name == settings.darkenWhenChecked) {
      input.checked = true;
    }

    var label = document.createElement("label");
    label.innerHTML = displayName;
    label.htmlFor = id;
    div.appendChild(label);

    container.appendChild(div);
  }
  createOption("", "None");
  for (var checkbox of settings.checkboxes) {
    createOption(checkbox, checkbox);
  }
}

function updateCheckboxStats(checkbox) {
  var checked = getStoredCheckboxRefs(checkbox).size;
  var total = pcbdata.modules.length - pcbdata.bom.skipped.length;
  var percent = checked * 100.0 / total;
  var td = document.getElementById("checkbox-stats-" + checkbox);
  td.firstChild.style.width = percent + "%";
  td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
}

document.onkeydown = function(e) {
  switch (e.key) {
    case "n":
      if (document.activeElement.type == "text") {
        return;
      }
      if (currentHighlightedRowId !== null) {
        checkBomCheckbox(currentHighlightedRowId, "placed");
        highlightNextRow();
        e.preventDefault();
      }
      break;
    case "ArrowUp":
      highlightPreviousRow();
      e.preventDefault();
      break;
    case "ArrowDown":
      highlightNextRow();
      e.preventDefault();
      break;
    default:
      break;
  }
  if (e.altKey) {
    switch (e.key) {
      case "f":
        focusFilterField();
        e.preventDefault();
        break;
      case "r":
        focusRefLookupField();
        e.preventDefault();
        break;
      case "z":
        changeBomLayout("bom-only");
        e.preventDefault();
        break;
      case "x":
        changeBomLayout("left-right");
        e.preventDefault();
        break;
      case "c":
        changeBomLayout("top-bottom");
        e.preventDefault();
        break;
      case "v":
        changeCanvasLayout("F");
        e.preventDefault();
        break;
      case "b":
        changeCanvasLayout("FB");
        e.preventDefault();
        break;
      case "n":
        changeCanvasLayout("B");
        e.preventDefault();
        break;
      default:
        break;
    }
    if (e.key >= '1' && e.key <= '9') {
      toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
    }
  }
}

function hideNetlistButton() {
  document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
  document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
  document.getElementById("bom-netlist-btn").style.display = "none";
}

window.onload = function(e) {
  initUtils();
  initRender();
  initStorage();
  initDefaults();
  cleanGutters();
  populateMetadata();
  dbgdiv = document.getElementById("dbg");
  bom = document.getElementById("bombody");
  bomhead = document.getElementById("bomhead");
  filter = "";
  reflookup = "";
  if (!("nets" in pcbdata)) {
    hideNetlistButton();
  }
  initDone = true;
  prepCheckboxes();
  // Triggers render
  changeBomLayout(settings.bomlayout);

  // Users may leave fullscreen without touching the checkbox. Uncheck.
  document.addEventListener('fullscreenchange', () => {
    if (!document.fullscreenElement)
      document.getElementById('fullscreenCheckbox').checked = false;
  });
}

window.onresize = resizeAll;
window.matchMedia("print").addListener(resizeAll);

///////////////////////////////////////////////

  </script>
</head>

<body>
<div id="topmostdiv" class="topmostdiv">
  <div id="top">
    <div style="float: right; height: 100%;">
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="menubtn"></button>
        <div class="menu-content">
          <label class="menu-label menu-label-top" style="width: calc(50% - 18px)">
            <input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)">
            Dark mode
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;">
            <input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)">
            Full Screen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)">
            Fab layer
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)">
            Silkscreen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)">
            References
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
            Values
          </label>
          <div id="tracksAndZonesCheckboxes">
            <label class="menu-label" style="width: calc(50% - 18px)">
              <input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)">
              Tracks
            </label><!-- This comment eats space! All of it!
            --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
              <input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)">
              Zones
            </label>
          </div>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)">
            Pads
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
            DNP outlined
          </label>
          <label class="menu-label">
            <input id="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)">
            Highlight first pin
          </label>
          <label class="menu-label">
            <input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
            Continuous redraw on drag
          </label>
          <label class="menu-label">
            <span>Board rotation</span>
            <span style="float: right"><span id="rotationDegree">0</span>&#176;</span>
            <input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Bom checkboxes</div>
            <input id="bomCheckboxes" class="menu-textbox" type=text
                   oninput="setBomCheckboxes(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Darken when checked</div>
            <div id="darkenWhenCheckedContainer"></div>
          </label>
          <label class="menu-label">
            <span class="shameless-plug">
              <span>Created using</span>
              <a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a>
            </span>
          </label>
        </div>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')"
                title="Front only">F
        </button>
        <button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')"
                title="Front and Back">FB
        </button>
        <button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')"
                title="Back only">B
        </button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')"
                title="BOM only"></button>
        <button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')"
                title="BOM left, drawings right"></button>
        <button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')"
                title="BOM top, drawings bot"></button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')"
                title="Grouped BOM"></button>
        <button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')"
                title="Ungrouped BOM"></button>
        <button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')"
                title="Netlist"></button>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="statsbtn"></button>
        <div class="menu-content">
          <table class="stats">
            <tbody>
              <tr>
                <td width="40%">Board stats</td>
                <td>Front</td>
                <td>Back</td>
                <td>Total</td>
              </tr>
              <tr>
                <td>Components</td>
                <td id="stats-components-front">~</td>
                <td id="stats-components-back">~</td>
                <td id="stats-components-total">~</td>
              </tr>
              <tr>
                <td>Groups</td>
                <td id="stats-groups-front">~</td>
                <td id="stats-groups-back">~</td>
                <td id="stats-groups-total">~</td>
              </tr>
              <tr>
                <td>SMD pads</td>
                <td id="stats-smd-pads-front">~</td>
                <td id="stats-smd-pads-back">~</td>
                <td id="stats-smd-pads-total">~</td>
              </tr>
              <tr>
                <td>TH pads</td>
                <td colspan=3 id="stats-th-pads">~</td>
              </tr>
            </tbody>
          </table>
          <table class="stats">
            <col width="40%"/><col />
            <tbody id="checkbox-stats">
              <tr>
                <td colspan=2 style="border-top: 0">Checkboxes</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="iobtn"></button>
        <div class="menu-content">
          <div class="menu-label menu-label-top">
            <div style="margin-left: 5px;">Save board image</div>
            <div class="flexbox">
              <input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
              <span>X</span>
              <input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
            </div>
            <label>
              <input id="render-save-transparent" type="checkbox">
              Transparent background
            </label>
            <div class="flexbox">
              <button class="savebtn" onclick="saveImage('F')">Front</button>
              <button class="savebtn" onclick="saveImage('B')">Back</button>
            </div>
          </div>
          <div class="menu-label">
            <span style="margin-left: 5px;">Config and checkbox state</span>
            <div class="flexbox">
              <button class="savebtn" onclick="saveSettings()">Export</button>
              <button class="savebtn" onclick="loadSettings()">Import</button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div id="fileinfodiv" style="overflow: auto;">
      <table class="fileinfo">
        <tbody>
          <tr>
            <td id="title" class="title" style="width: 70%">
              Title
            </td>
            <td id="revision" class="title" style="width: 30%">
              Revision
            </td>
          </tr>
          <tr>
            <td id="company">
              Company
            </td>
            <td id="filedate">
              Date
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <div id="bot" class="split" style="height: calc(100% - 80px)">
    <div id="bomdiv" class="split split-horizontal">
      <div style="width: 100%">
        <input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup"
               oninput="updateRefLookup(this.value)">
        <input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter"
               oninput="updateFilter(this.value)">
        <div class="button-container hideonprint" style="float: left; margin: 0;">
          <button id="copy" title="Copy bom table to clipboard"
               onclick="copyToClipboard()"></button>
        </div>
      </div>
      <div id="dbg"></div>
      <table class="bom">
        <thead id="bomhead">
        </thead>
        <tbody id="bombody">
        </tbody>
      </table>
    </div>
    <div id="canvasdiv" class="split split-horizontal">
      <div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
      <div id="backcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
    </div>
  </div>
</div>
</body>

</html>
